﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Hive.Core.Common.Shell;

namespace Hive.Core.Model
{
    /// <summary>
    /// A default implementation of a hive.
    /// </summary>
    public class DefaultHive : IHive
    {
        private readonly DirectoryInfo directory;
        private readonly HiveConfiguration configuration;
        private readonly ISourceRepository sourceRepository;
        private readonly IBinaryRepository binaryRepository;

        /// <summary>
        /// Create a hive.
        /// </summary>
        /// <param name="directory">The hive directory.</param>
        /// <param name="configuration">The hive configuration.</param>
        /// <param name="sourceRepository">The source repository.</param>
        /// <param name="binaryRepository">The binary repository.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="configuration"/>,
        /// <paramref name="directory"/>, <paramref name="sourceRepository"/> or <paramref name="binaryRepository"/> is null.</exception>
        public DefaultHive(DirectoryInfo directory, HiveConfiguration configuration, ISourceRepository sourceRepository, IBinaryRepository binaryRepository)
        {
            if (directory == null)
                throw new ArgumentNullException("directory");
            if (configuration == null)
                throw new ArgumentNullException("configuration");
            if (sourceRepository == null)
                throw new ArgumentNullException("sourceRepository");
            if (binaryRepository == null)
                throw new ArgumentNullException("binaryRepository");

            this.directory = directory;
            this.configuration = configuration;
            this.sourceRepository = sourceRepository;
            this.binaryRepository = binaryRepository;
        }

        /// <inheritdoc />
        public HiveConfiguration Configuration
        {
            get { return configuration; }
        }

        /// <inheritdoc />
        public string Name
        {
            get { return directory.Name; }
        }

        /// <inheritdoc />
        public DirectoryInfo Directory
        {
            get { return directory; }
        }

        /// <inheritdoc />
        public ISourceRepository SourceRepository
        {
            get { return sourceRepository; }
        }

        /// <inheritdoc />
        public IBinaryRepository BinaryRepository
        {
            get { return binaryRepository; }
        }

        /// <inheritdoc />
        public IList<IPackage> GetPackages()
        {
            return directory.GetDirectories().Select(x => new DefaultPackage(this, x)).ToArray();
        }

        /// <inheritdoc />
        public IPackage GetPackage(string packageName)
        {
            if (packageName == null)
                throw new ArgumentNullException("packageName");

            return new DefaultPackage(this, new DirectoryInfo(Path.Combine(directory.FullName, packageName)));
        }

        /// <inheritdoc />
        public bool FindPackageBranch(DirectoryInfo currentDirectory, out string packageName, out string branchName)
        {
            if (currentDirectory == null)
                throw new ArgumentNullException("currentDirectory");

            for (;;)
            {
                if (currentDirectory.Parent == null || currentDirectory.Parent.Parent == null)
                {
                    packageName = null;
                    branchName = null;
                    return false;
                }

                if (currentDirectory.Parent.Parent.FullName == directory.FullName)
                {
                    packageName = currentDirectory.Parent.Name;
                    branchName = currentDirectory.Name;
                    return true;
                }

                currentDirectory = currentDirectory.Parent;
            }
        }
    }
}
